/**
 *	@file	bonguri.c
 *	@brief	ボングリセーブデータ
 *	@author	Miyuki Iwasawa
 *	@date	08.09.02
 */

#include "common.h"
#include "savedata/savedata.h"
#include "savedata/bonguri.h"
#include "system/pm_str.h"
#include "system/buflen.h"
#include "system/msgdata.h"
#include "gflib/strbuf.h"
#include "gflib/strbuf_family.h"

#include "bonguri_local.h"
#include "itemtool/itemsym.h"

#include "msgdata/msg.naix"
#include "msgdata/msg_bong_case.h"

///カラーチェック
#define BONG_COL_CHECK(col) { \
 if(col >= BONG_COL_MAX){ \
	GF_ASSERT_MSG(0,"BonguriSubエラー　不正カラー%d\n",col); \
	return 0; \
 } \
}

typedef struct _FLAVOR_DATA{
	u8	flavor;
	u8	level;
}FLAVOR_DATA;

typedef struct _BONGURI_PARAM{
	s8	flavor[BONG_FTYPE_MAX];
}BONGURI_PARAM;

//ボングリのパラメータテーブル
static const BONGURI_PARAM BonguriParamTable[] = {
 //からい、すっぱい、しぶい、にがい、あまい
 {4,-2,0,0,0},	///<RED
 {0,4,-2,0,0},	///<YELLOW
 {0,0,4,-2,0},	///<BLUE
 {0,0,0,4,-2},	///<GREEN
 {-2,0,0,0,4},	///<PINK
 {-2,-2,-2,-2,-2},	///<WHITE
 {2,2,2,2,2},	///<BLACK
};

///NPCボンジュースのデータ
static const BONG_JUICE DATA_BongJuiceTable[] = {
 //人気値、まろやかさ、
 {  0,116,	22,10,0,0,0},	//タケ
 {150,120,	0,20,14,0,0},	//リサ
 {540,125,	0,0,28,20,0},	//ギルモア
 {200,136,	0,0,0,24,14},	//ユキ
 {150,104,	12,0,0,0,20},	//ヒデ
};


enum{
 GFL_MODE_MAIN,
 GFL_MODE_SUB,
 GFL_MODE_HIDE,
};

static void bongjuice_MildParamAdd(BONGURI_SAVE* sv,u8 add);
static void bongjuice_MildParamSub(BONGURI_SAVE* sv,u8 sub);
static void bongjuice_TasteCalc(BONGURI_SAVE* sv);
static u8 bongjuice_GetFlavorRank(u8 mode,u8 param);
static void bongjuice_FPrmSet(BONGJUICE_FPRM* pbf,FLAVOR_DATA* dat,int mode);
static void juice_FlavorArrayGet(BONG_JUICE* juice,s8* tbl);
static void commjuice_Clear(BONG_JUICE_COMM* comm_juice);

/**
 *	@brief	ボングリデータサイズ取得
 */
int BonguriSave_GetWorkSize(void)
{
	IWASAWA_PRINT("ボングリセーブサイズ %d\n",sizeof(BONGURI_SAVE));
	return sizeof(BONGURI_SAVE);
}

/**
 *	@brief	ボングリジュース通信データ型サイズ取得(１人分)
 */
int BonguriSave_GetBongJuiceCommWorkSize(void)
{
	return sizeof(BONG_JUICE_COMM);
}

/**
 *	@brief	ボングリセーブデータブロックへのポインタ取得
 */
BONGURI_SAVE* SaveData_GetBonguriSave(SAVEDATA* sv)
{
	return SaveData_Get(sv,GMDATA_ID_BONGURI_SAVE);
}

/**
 *	@brief	ボングリセーブデータクリア
 */
void BonguriSave_Clear(BONGURI_SAVE* sv)
{
	MI_CpuClear8(sv,sizeof(BONGURI_SAVE));

	BongJuice_Clear(&sv->juice);

	BonguriSave_CommJuiceAllClear(sv);
}

/**
 *	@brief	ボングリジュースデータ　オールクリア
 */
void BonguriSave_CommJuiceAllClear(BONGURI_SAVE* sv)
{
	int i;

	for(i = 0;i < BONGJUICE_COMMDATA_MAX;i++){
		commjuice_Clear(&sv->comm[i]);
	}
}

/**
 *	@brief	ボングリセーブデータ初期化
 */
void BonguriSave_Init(BONGURI_SAVE* sv)
{
	BonguriSave_Clear(sv);
}

/**
 *	@brief	ボングリジュースデータ初期化
 */
void BongJuice_Clear(BONG_JUICE* juice)
{
	MI_CpuClear8(juice,sizeof(BONG_JUICE));
}

/**
 *	@brief	ボングリを追加する
 *
 *	@param	col	ボングリのカラー
 *	@param	add_num	追加数
 *
 *	@return	追加後の総数
 */
u8 BonguriSave_BonguriAdd(BONGURI_SAVE* sv,BONG_COLOR col,u8 add_num)
{
	BONG_COL_CHECK(col);

	if(sv->bong[col] + add_num > BONGURI_KEEP_MAX){
		sv->bong[col] = BONGURI_KEEP_MAX;
	}else{
		sv->bong[col] += add_num;
	}
	return sv->bong[col];
}

/**
 *	@brief	ボングリを消費する
 *
 *	@param	col	ボングリのカラー
 *	@param	sub_num	消費数
 *
 *	@return	指定数を消費後の残り数
 *
 *	＊指定数を消費できなかった場合、なにもせずにかえります
 */
u8 BonguriSave_BonguriSub(BONGURI_SAVE* sv,BONG_COLOR col,u8 sub_num)
{
	BONG_COL_CHECK(col);

	if(sv->bong[col] >= sub_num){
		sv->bong[col] -= sub_num;
		IWASAWA_PRINT("ぼんぐり消費 %d -> %dこ\n",col,sub_num);
	}
	return sv->bong[col];
}

/**
 *	@brief	ボングリの手持ち数を取得
 */
u8 BonguriSave_GetBonguriNum(BONGURI_SAVE* sv,BONG_COLOR col)
{
	BONG_COL_CHECK(col);
	return sv->bong[col];
}

/**
 *	@brief	ボングリの手持ち数をセット
 */
u8 BonguriSave_SetBonguriNum(BONGURI_SAVE* sv,BONG_COLOR col,u8 num)
{
	BONG_COL_CHECK(col);
	if(num > BONGURI_KEEP_MAX){
		num = BONGURI_KEEP_MAX;
	}
	sv->bong[col] = num;
	return sv->bong[col];
}

/**
 *	@brief	ガンテツにボングリを預ける(ボングリ消費処理込み)
 */
void BonguriSave_KeepBonguri(BONGURI_SAVE* sv,BONG_COLOR col,u8 set_num)
{
	if(sv->bong[col] < set_num){
		GF_ASSERT_MSG(0,"ガンテツに預けようとしているボングリ数が不正です\n");
		return;
	}
	sv->mb_color = col;
	sv->mb_num = set_num;

	BonguriSave_BonguriSub(sv,col,set_num);
}

/**
 *	@brief	ガンテツに預けているボングリの個数を取得する
 */
u8 BonguriSave_GetKeepBonguriNum(BONGURI_SAVE* sv)
{
	return sv->mb_num;
}

/*
 *	@brief　ガンテツに預けたボングリの種類から、もらえるアイテムナンバーを返す
 */
u16 BonguriSave_ExchangeKeepBonguri(BONGURI_SAVE* sv)
{
	static const u16 ball[] = {
		ITEM_REBERUBOORU,	//RED
		ITEM_MUUNBOORU,		//YELLOW
		ITEM_RUAABOORU,		//BLUE
		ITEM_HURENDOBOORU,	//GREEN
		ITEM_RABURABUBOORU,	//PINK
		ITEM_SUPIIDOBOORU,	//WHITE
		ITEM_HEBIIBOORU,	//BLACK
	};
	if(sv->mb_color >= BONG_COL_MAX){
		return ITEM_MONSUTAABOORU;
	}
	return ball[sv->mb_color];
}

/*
 *	@brief	起動メッセージフラグをセット
 */
void BonguriSave_SetStartupFlag(BONGURI_SAVE* sv,BONG_STARTUP flag)
{
	sv->startup_f = flag;
}

/*
 *	@brief	起動メッセージフラグを取得
 */
BONG_STARTUP BonguriSave_GetStartupFlag(BONGURI_SAVE* sv)
{
	return sv->startup_f;
}

/**
 *	@brief	ポットにセットされたボングリの数を取得する
 */
u8	BonguriSave_GetStockNum(BONGURI_SAVE* sv)
{
	int i;
	u8	num = 0;
	u16	stock = sv->stock.stock;

	for(i = 0;i < BONGJUICE_STOCK_MAX;i++){
		if(stock & BONG_STOCK_MASK_BIT){	//0でなければストックされている
			++num;
		}
		stock >>= BONG_STOCK_SHIFT_BIT;
	}
	return num;
}

/**
 *	@brief	ポットにボングリをセットする(ボングリ消費処理込み)
 *
 *	@param	col	セットするボングリカラー
 *	@param	walk_ct	現在の歩数カウント
 *
 *	@retval	TRUE セットできた
 *	@retval	FALSE セットできなかった
 */
BOOL BonguriSave_SetStock(BONGURI_SAVE* sv,BONG_COLOR col,u32 walk_ct)
{
	int i;
	u8	num = 0;
	u16	stock = sv->stock.stock;

	BONG_COL_CHECK(col);

	for(i = 0;i < BONGJUICE_STOCK_MAX;i++){
		if(stock & BONG_STOCK_MASK_BIT){	//0でなければストックされている
			++num;
			stock >>= BONG_STOCK_SHIFT_BIT;
			IWASAWA_PRINT("ぼんぐりストックチェック %d -> %d true\n",i,(stock&BONG_STOCK_MASK_BIT));
			continue;
		}
		IWASAWA_PRINT("ぼんぐりストックチェック %d -> %d false\n",i,col);
		stock = ((col+1) & BONG_STOCK_MASK_BIT) << (BONG_STOCK_SHIFT_BIT*i);
		sv->stock.stock |= stock;
		sv->stock.s_flag = TRUE;
		sv->start_ct = walk_ct;
		if(!sv->juice_rest){
			sv->mild_ct = walk_ct;
		}
		sv->make_ct = 0;
		BonguriSave_BonguriSub(sv,col,1);

		return TRUE;
	}
	return FALSE;
}

/**
 *	@brief	ポットの状態を取得
 */
int BonguriSave_GetPotState(BONGURI_SAVE* sv)
{
	//ストックがない
	if(!BonguriSave_GetStockNum(sv)){
		return BONG_POT_NULL;
	}
	if(sv->make_ct < 50){
		return BONG_POT_WALK01;
	}else if(sv->make_ct < 80){
		return BONG_POT_WALK02;
	}
	return BONG_POT_WALK03;
}

/**
 *	@brief	日付変更でジュースのまろやかさがアップ
 */
void BonguriSave_JuiceDayUpdate(BONGURI_SAVE* sv,s32 diff_days)
{
	int up = diff_days*10;
	if(sv->juice_rest == 0){
		return;	//ジュースがなければなにもしない
	}
	if((int)sv->juice.mild + up > 255){
		sv->juice.mild = 255;
	}else{
		sv->juice.mild += up;
	}
}

/**
 *	@brief	ジュースの残量取得
 */
u8 BonguriSave_GetJuiceRestCount(BONGURI_SAVE* sv)
{
	return sv->juice_rest;
}
/**
 *	@brief	ジュースの残量セット
 */
void BonguriSave_SetJuiceRestCount(BONGURI_SAVE* sv,u8 rest)
{
	if(rest >= 3 ){
		rest = 3;
	}
	sv->juice_rest = rest;
	if(rest  == 0){
		BongJuice_Clear(&sv->juice);
		sv->mild_ct = 0;
		sv->start_ct = 0;
		sv->make_ct = 0;
	}
}

/**
 *	@brief	ボングリジュースのパラメータを取得
 */
BOOL BonguriSave_GetJuiceParam(BONGURI_SAVE* sv,BONG_JUICE_ID id,BONG_JUICE* juice)
{
	if(id >= BONG_JUICE_ID_MAX){
		id = BONG_JUICE_NPC01;
	}
	if(id <= BONG_JUICE_NPC05){
		*juice = DATA_BongJuiceTable[id-BONG_JUICE_NPC01];
	}else if(id <= BONG_JUICE_COMM03){
		if(BongJuice_GetTasteLevel(&sv->comm[id-BONG_JUICE_COMM01].juice) == 0){
			BongJuice_Clear(juice);
			return FALSE;
		}
		*juice = sv->comm[id-BONG_JUICE_COMM01].juice;
	}else{
		//自分のデータ
		if(sv->juice_rest == 0){
			BongJuice_Clear(juice);
			return FALSE;
		}
		*juice = sv->juice;
	}
	return TRUE;
}

/**
 *	@brief	ジュースのパラメータが有効かどうか取得
 */
BOOL BongJuice_IsEnable(BONG_JUICE* juice)
{
	int i;
	if(BongJuice_GetTasteLevel(juice) == 0){
		return FALSE;
	}
	return TRUE;
}

/**
 *	@brief	ジュースの味レベルを取得
 */
u8 BongJuice_GetTasteLevel(BONG_JUICE* juice)
{
	int i;
	u16	taste = 0;

	for(i = 0;i < BONG_FTYPE_MAX;i++){
		taste += juice->param[i];
	}
	if(taste > 100){
		taste = 100;
	}
	return taste;
}

/**
 *	@brief	ジュースの各味レベルをゲット
 */
u8 BonguriSave_GetFlavorLevel(BONGURI_SAVE* sv,BONG_FTYPE ftype)
{
	if(ftype >= BONG_FTYPE_MAX){
		return 0;
	}
	return sv->juice.param[ftype];
}
/**
 *	@brief	ジュースの各味レベルをセット
 */
void BonguriSave_SetFlavorLevel(BONGURI_SAVE* sv,BONG_FTYPE ftype,u8 taste)
{
	if(ftype >= BONG_FTYPE_MAX){
		return;
	}
	sv->juice.param[ftype] = taste;
}

/**
 *	@brief	ジュースのマイルドさを取得
 */
u8 BonguriSave_GetMildLevel(BONGURI_SAVE* sv)
{
	if(sv->juice_rest == 0){
		return 0;
	}
	return sv->juice.mild;
}

/**
 *	@brief	ジュースのマイルドさをセット
 */
void BonguriSave_SetMildLevel(BONGURI_SAVE* sv,u8 mild)
{
	if(sv->juice_rest == 0){
		return;
	}
	sv->juice.mild = mild;
}


/**
 *	@brief	ジュースの味値詳細を取得
 */
void BongJuice_GetFlavorParam(BONG_JUICE* juice,BONGJUICE_FLAVOR* pbf)
{
	int i,j;
	u8	flavor_ct = 0, val= 0;
	FLAVOR_DATA	tbl[BONG_FTYPE_MAX];

	MI_CpuClear8(pbf,sizeof(BONGJUICE_FLAVOR));
	MI_CpuClear8(tbl,sizeof(FLAVOR_DATA)*BONG_FTYPE_MAX);

	//味値チェック
	flavor_ct = 0;
	for(i = 0;i < BONG_FTYPE_MAX;i++){
		u8	level;
		level = juice->param[i];

		tbl[i].flavor = i;
		tbl[i].level = level;
		if(level == 0){
			continue;
		}
		flavor_ct++;
	}

	//味レベルソート
	if(flavor_ct > 0){
		for(i = 0;i < BONG_FTYPE_MAX;i++){
			FLAVOR_DATA tmp;
			for(j = i+1;j < BONG_FTYPE_MAX;j++){
				if(	(tbl[i].level > tbl[j].level) ||
					((tbl[i].level == tbl[j].level) && (tbl[i].flavor < tbl[j].flavor))){
					continue;
				}
				tmp = tbl[i];
				tbl[i] = tbl[j];
				tbl[j] = tmp;
			}
		}
	}

	val = tbl[4].level;
	for(i = 0;i < BONG_FTYPE_MAX;i++){	//味値プライオリティ格納
		pbf->order[i] = tbl[i].flavor;
		if(val == tbl[i].level){
			pbf->min_ct++;
		}
	}

	pbf->ct = flavor_ct;
	switch(flavor_ct){
	case 0:	//味がない
		pbf->main.flavor = BONG_FLAVOR_NONE;
		return;
	case 1:	//メインのみ
		bongjuice_FPrmSet(&pbf->main,&tbl[0],GFL_MODE_MAIN);
		pbf->sub.flavor = BONG_FLAVOR_NONE;
		break;
	case 2:	//メイン・サブのみ
		bongjuice_FPrmSet(&pbf->main,&tbl[0],GFL_MODE_MAIN);
		bongjuice_FPrmSet(&pbf->sub,&tbl[1],GFL_MODE_SUB);
		pbf->hide.flavor = BONG_FLAVOR_NONE;
		break;
	case 3:	//メイン・サブ・隠し
		bongjuice_FPrmSet(&pbf->main,&tbl[0],GFL_MODE_MAIN);
		bongjuice_FPrmSet(&pbf->sub,&tbl[1],GFL_MODE_SUB);
		bongjuice_FPrmSet(&pbf->hide,&tbl[2],GFL_MODE_HIDE);
		break;
	case 4:
	case 5:
		if((tbl[0].level - tbl[3].level) <= 12){	//雑味系
			pbf->main.flavor = BONG_FLAVOR_MIX;
			pbf->main.level = tbl[0].level;
			pbf->sub.flavor = BONG_FLAVOR_NONE;
			pbf->sub.level = tbl[1].level;
			pbf->hide.flavor = BONG_FLAVOR_NONE;
			pbf->hide.level = tbl[2].level;
			pbf->ct = 1;
			if(tbl[0].level > 20){
				pbf->main.rank = BONGJUICE_FRANK_3;
			}else if(tbl[0].level > 7)	{
				pbf->main.rank = BONGJUICE_FRANK_2;
			}else{
				pbf->main.rank = BONGJUICE_FRANK_1;
			}
			break;
		}
		bongjuice_FPrmSet(&pbf->main,&tbl[0],GFL_MODE_MAIN);
		bongjuice_FPrmSet(&pbf->sub,&tbl[1],GFL_MODE_SUB);

		if(flavor_ct == 4){	//○○を消している
			bongjuice_FPrmSet(&pbf->hide,&tbl[4],GFL_MODE_HIDE);
			break;
		}else{	//ざつみが口に残る
			pbf->hide.flavor = BONG_FLAVOR_MIX;
			pbf->hide.rank = BONGJUICE_FRANK_1;
		}
		pbf->hide.level = tbl[2].level;
		break;
	}
	pbf->ct = flavor_ct;
}

/**
 *	@brief	ジュースの色を返す
 */
BONG_FTYPE BongJuice_GetJuiceColor(BONG_JUICE* juice)
{
	BONGJUICE_FLAVOR bf;

	//味詳細取得
	BongJuice_GetFlavorParam(juice,&bf);

	if(bf.main.flavor >= BONG_FLAVOR_MIX){
		return BONG_FLAVOR_MIX;
	}
	return bf.main.flavor;
}

/**
 *	@brief	ボンジュースデータ ジュースの名前IDを取得
 */
BONGJUICE_NAME_ID BongJuice_GetNameID(BONG_JUICE* juice)
{
	BONGJUICE_FLAVOR flavor;

	BongJuice_GetFlavorParam(juice,&flavor);

	if(flavor.ct == 0){
		return BONGJUICE_NAME_PLANE;
	}
	return flavor.order[0]+BONGJUICE_NAME_HOT;
}

/**
 *	@brief	ジュースを消費する
 */
int BonguriSave_UseJuice(BONGURI_SAVE* sv)
{
	if(sv->juice_rest == 0){
		return 0;
	}
	sv->juice_rest--;

	if(sv->juice_rest == 0){
		BongJuice_Clear(&sv->juice);
		sv->mild_ct = 0;
		sv->start_ct = 0;
		sv->make_ct = 0;
	}
	return sv->juice_rest;
}

/**
 *	@brief	ジュースの状態を歩数でアップデートする
 *
 *	@param	now_walk_ct	最新の歩数
 */
void BonguriSave_JuiceStateUpdate(BONGURI_SAVE* sv,u32 now_walk_ct)
{
	int count = 0,surplus = 0;
	u32	diff = 0;

	if((!sv->stock.s_flag) && (!sv->juice_rest)){
		return;
	}
	//現在の差分値更新
	diff = now_walk_ct-sv->mild_ct;
	if(diff >= BONGJUICE_UPDATE_CT){	//まろやかさアップ
		count = diff/BONGJUICE_UPDATE_CT;
		surplus = diff%BONGJUICE_UPDATE_CT;
		bongjuice_MildParamAdd(sv,(u8)count);
		sv->mild_ct = now_walk_ct - surplus;
	}
	if(!sv->stock.s_flag){
		return;
	}
	sv->make_ct = now_walk_ct-sv->start_ct;

	if(sv->make_ct < BONGJUICE_UPDATE_CT){
		return;	//なにもしない
	}

	//起動状態セット
	if(sv->juice_rest){
		BonguriSave_SetStartupFlag(sv,BONG_STARTUP_UPDATE);
	}else{
		BonguriSave_SetStartupFlag(sv,BONG_STARTUP_NEW);
	}
	bongjuice_TasteCalc(sv);
	return;
}

/*
 *	@brief　ボンジュース送信データを生成
 *
 *	@param	sv	ボングリセーブ
 *	@param	my	MYSTATUS
 *	@param	fun_num	ポケスロンの人気値
 *
 *	@li	プレイヤーのジュースパラメータをAllocしたメモリに格納して返します
 *	@li	要らなくなったら呼び出し側が責任もって解放してください
 */
void* BongSave_BongJuiceCommDataAlloc(BONGURI_SAVE* sv,MYSTATUS* my,u32 fun_num,int heapID)
{
	BONG_JUICE_COMM* jp;

	jp = sys_AllocMemoryLo(heapID,sizeof(BONG_JUICE_COMM));
	MI_CpuClear8(jp,sizeof(BONG_JUICE_COMM));

	jp->tr_id = MyStatus_GetID(my);
	jp->tr_sex = MyStatus_GetMySex(my);
	jp->region = MyStatus_GetRegionCode(my);
	jp->version = MyStatus_GetRomCode(my);
	PM_strclearEOM_( jp->name, PERSON_NAME_SIZE+EOM_SIZE);
	PM_strncpy( jp->name, MyStatus_GetMyName(my), PERSON_NAME_SIZE);

	BonguriSave_GetJuiceParam(sv,BONG_JUICE_MINE,&jp->juice);
	if(fun_num > 65535){
		jp->juice.popurar = 65535;
	}else{
		jp->juice.popurar = fun_num;
	}

	return (void*)jp;
}

#define COMM_PLAYER_MAX	(4)

/**
 *	@brief	同一プレイヤーのデータか確認
 */
static BOOL sub_IsSamePlayerJuice(BONG_JUICE_COMM* s1,BONG_JUICE_COMM* s2)
{
	if(s1->tr_id != s2->tr_id){
		return FALSE;
	}
	if(s1->tr_sex != s2->tr_sex){
		return FALSE;
	}
	if(s1->version != s2->version){
		return FALSE;
	}
	if(s1->region != s2->region){
		return FALSE;
	}
	if(PM_strcmp(s1->name,s2->name)){
		return FALSE;
	}
	return TRUE;
}

/**
 *	@brief	ボンジュースデータ受信
 *
 *	@param	sv	ボングリセーブデータへのポインタ
 *	@param	buf	受信データバッファへのポインタ(BONG_JUICE_COMM構造体の人数分の配列になるハズ)
 *	@param	num	有効データ数(通信クライアントの数)
 *	@param	net_id	自分の通信ID
 */
void BongSave_BongJuiceCommDataSet(BONGURI_SAVE* sv,void* buf,int player_num,int net_id)
{
	u8 del_id = 0,flag = 0,write_pos = 0;
	int i,j,num;
	BONG_JUICE_COMM* jsp = (BONG_JUICE_COMM*)buf;

	//現在の有効データ数チェック
	num = 0;
	for(i = 0;i < BONGJUICE_COMMDATA_MAX;i++){
		if((!BongJuice_IsEnable(&sv->comm[i].juice))){
			break;
		}
		num++;
	}
	OS_Printf("NowJuiceNum = %d\n",num);

	//上書きデータ確認
	for(i = 0;i < player_num;i++){
		OS_Printf("//-------------------------------------\nStart JuiceParam%d net_id = %d, tr_id = %d, taste = %d\n",
					i,net_id,jsp[i].tr_id,BongJuice_GetTasteLevel(&jsp[i].juice));
		if(i == net_id || (!BongJuice_IsEnable(&jsp[i].juice))){
			continue;
		}
		//同じプレイヤーのデータが既にあるかチェック
		flag = 0;
		del_id = 0;
		for(j = 0;j < BONGJUICE_COMMDATA_MAX;j++){
			if(sub_IsSamePlayerJuice(&jsp[i],&sv->comm[j])){
				del_id = j;
				flag = 1;
				break;
			}
		}
#ifdef PM_DEBUG
		if(flag){
			OS_Printf("同じ人のジュース発見 net_id = %d -> juice_id = %d\n",i,del_id);
		}
#endif
		//削除チェック
		if(num >= BONGJUICE_COMMDATA_MAX){
			write_pos = (BONGJUICE_COMMDATA_MAX-1);	//書き込み位置は最後で数は増えない
			flag = 1;
		}else{
			if(flag){
				write_pos = num-1;
			}else{
				write_pos = num++;	//数が増える
			}
		}
		OS_Printf("write_pos = %d new_num = %d 上書きflag = %d\n",write_pos,num,flag);
		//必要ならデータを詰める
		if(flag && (del_id < write_pos)){
			for(j = del_id;j < (num-1);j++){
				sv->comm[j] = sv->comm[j+1];
			}
			OS_Printf("data del %d番から後を%dこ詰める\n",del_id,write_pos-del_id);
		}
		//write_posにデータを格納
		sv->comm[write_pos] = jsp[i];
		OS_Printf("データ書き込み JuiceParam write_pos = %d, tr_id = %d, taste = %d\n\n",
				write_pos,sv->comm[write_pos].tr_id,BongJuice_GetTasteLevel(&sv->comm[write_pos].juice));
	}
	return;
}

/**
 *	@brief	ボンジュースデータ ユーザー名を取得
 *
 *	自分の名前は取れません
 */
STRBUF* BongSave_BongJuiceUserNameAlloc(BONGURI_SAVE* sv,BONG_JUICE_ID juice_id,int heapID)
{
	STRBUF* name;
	name = STRBUF_Create(BUFLEN_PERSON_NAME+EOM_SIZE,heapID);

	if(juice_id < BONG_JUICE_COMM01){
		MSGDATA_MANAGER *man = MSGMAN_Create(MSGMAN_TYPE_DIRECT, ARC_MSG, NARC_msg_bong_case_dat, heapID);
		MSGMAN_GetString(man,msg_bongjuice_user01+(juice_id-BONG_JUICE_NPC01),name);
		MSGMAN_Delete(man);
	}else if(juice_id < BONG_JUICE_MINE){
		u8 idx = juice_id-BONG_JUICE_COMM01;
		if(BongJuice_IsEnable(&sv->comm[idx].juice)){
			STRBUF_SetStringCode( name, sv->comm[idx].name );
		}
	}
	return name;
}

/**
 *	@brief	ボンジュースデータ ジュース名を取得
 */
STRBUF* BongSave_BongJuiceNameAlloc(BONGURI_SAVE* sv,BONG_JUICE_ID juice_id,int heapID)
{
	STRBUF* name;
	BONG_JUICE juice;

	BonguriSave_GetJuiceParam(sv,juice_id,&juice);

	{
		MSGDATA_MANAGER *man = MSGMAN_Create(MSGMAN_TYPE_DIRECT, ARC_MSG, NARC_msg_bong_case_dat, heapID);
		name = MSGMAN_AllocString(man,msg_juice_flavor01+BongJuice_GetNameID(&juice));
		MSGMAN_Delete(man);
	}
	return name;
}




/**
 *	@brief	ジュースのまろやかさ操作
 */
static void bongjuice_MildParamAdd(BONGURI_SAVE* sv,u8 add)
{
	if(sv->juice.mild + add > BONGJUICE_MILD_MAX){
		sv->juice.mild = BONGJUICE_MILD_MAX;
	}else{
		sv->juice.mild += add;
	}
}
static void bongjuice_MildParamSub(BONGURI_SAVE* sv,u8 sub)
{
	if(sv->juice.mild > sub){
		sv->juice.mild = 0;
	}else{
		sv->juice.mild -= sub;
	}
}

/**
 *	@brief	ジュースの味操作
 */
static void bongjuice_TasteCalc(BONGURI_SAVE* sv)
{
	int i,j,k;
	u8	taste,col,max,max_idx;
	u16	stock = sv->stock.stock;
	s8	flavor[BONG_FTYPE_MAX];
	s8	level[BONG_FTYPE_MAX];

	//現在の値のコピーを取得
	juice_FlavorArrayGet(&sv->juice,flavor);

	//ストックパラメータを反映
	for(i = 0;i < BONGJUICE_STOCK_MAX;i++){
		u8 mild_sub_f;

		mild_sub_f = FALSE;

		col = stock & BONG_STOCK_MASK_BIT;
		if(!col){	//0でなければストックされている
			break;
		}
		//味値計算
		taste = 0;
		max = max_idx = 0;
		col -= 1;	//カラー定義自体は0オリジンなので-1補正しておく

		//最新の味レベルソート
		for(j = 0;j < BONG_FTYPE_MAX;j++){
			level[j] = j;
			IWASAWA_PRINT("f%d:%d, ",j,flavor[j]);
		}
		IWASAWA_PRINT("\n");
		for(j = 0;j < 2;j++){
			s8 tmp;
			for(k = j+1;k < BONG_FTYPE_MAX;k++){
				if(	(flavor[level[j]] > flavor[level[k]] ) ||
					((flavor[level[j]] == flavor[level[k]]) && (level[j] < level[k]))){
					continue;
				}
				tmp = level[j];
				level[j] = level[k];
				level[k] = tmp;
			}
		}
		IWASAWA_PRINT("stock%d main = %d,sub = %d\n",i,level[0],level[1]);

		for(j = 0;j < BONG_FTYPE_MAX;j++){
			s8	diff = BonguriParamTable[col].flavor[j];
			s8	val = flavor[j] + diff;

			if((diff > 0) && ((flavor[level[0]] != 0) && (level[0] != j)) && ((flavor[level[1]] != 0) && (level[1] != j))){
				mild_sub_f = TRUE;
			}
			if(val >= BONG_JUICE_FLAVOR_VAL_MAX){
				val = BONG_JUICE_FLAVOR_VAL_MAX;
			}else if(val < 0){
				val = 0;
			}
			//非上昇値&パラメータダウン候補値チェック(黒ボングリは例外として上昇値も処理)
			if(col == BONG_COL_BLACK || (val <= flavor[j])){
				if(val > max){	//非上昇値の最大を保存
					max = val;
					max_idx = j;
				}
			}
			flavor[j] =val;	//値更新
			taste += val;
		}
		stock >>= BONG_STOCK_SHIFT_BIT;

		if(mild_sub_f){	//まろやかさ減算チェック
			if(sv->juice.mild < 10){
				sv->juice.mild = 0;
			}else{
				sv->juice.mild -= 10;
			}
			IWASAWA_PRINT("%d mild down = %d\n",i,sv->juice.mild);
		}
		//味値上限チェック
		if(col == BONG_COL_WHITE || taste <= 100){
			continue;
		}
		//オーバーしている場合、ダウン候補から下げる
		flavor[max_idx] -= (taste-100);
	}
	//補正後の値を書き戻し
	for(i = 0;i < BONG_FTYPE_MAX;i++){
		sv->juice.param[i] = flavor[i];
	}
	sv->juice_rest = BONGJUICE_USE_MAX;

	//ストックをクリア
	sv->stock.stock = 0;
}

/**
 *	@brief	ジュースの味覚値を配列にコピーして返す
 */
static void juice_FlavorArrayGet(BONG_JUICE* juice,s8* tbl)
{
	int i;

	for(i = 0;i < BONG_FTYPE_MAX;i++){
		tbl[i] = juice->param[i];
	}
}

/**
 *	@brief	ジュースの味値レベルを返す
 */
static u8 bongjuice_GetFlavorRank(u8 mode,u8 param)
{
	if(param == 0){
		return BONGJUICE_FRANK_0;
	}
	switch(mode){
	case GFL_MODE_MAIN:
		if(param > 62){
			return BONGJUICE_FRANK_6;
		}else if(param > 50){
			return BONGJUICE_FRANK_5;
		}else if(param > 40){
			return BONGJUICE_FRANK_4;
		}else if(param > 30){
			return BONGJUICE_FRANK_3;
		}else if(param > 20){
			return BONGJUICE_FRANK_2;
		}else if(param > 0){
			return BONGJUICE_FRANK_1;
		}
		break;
	case GFL_MODE_SUB:
		if(param > 40){
			return BONGJUICE_FRANK_4;
		}else if(param > 30){
			return BONGJUICE_FRANK_3;
		}else if(param > 20){
			return BONGJUICE_FRANK_2;
		}else if(param > 0){
			return BONGJUICE_FRANK_1;
		}
		break;
	case GFL_MODE_HIDE:
		if(param > 20){
			return BONGJUICE_FRANK_3;
		}else if(param > 10){
			return BONGJUICE_FRANK_2;
		}else if(param > 0){
			return BONGJUICE_FRANK_1;
		}
		break;
	}
	return BONGJUICE_FRANK_0;
}

/**
 *	@brief	BONGJUICE_FPRM型にデータセット
 */
static void bongjuice_FPrmSet(BONGJUICE_FPRM* pbf,FLAVOR_DATA* dat,int mode)
{
	pbf->flavor = dat->flavor;
	pbf->level = dat->level;
	pbf->rank = bongjuice_GetFlavorRank(mode,dat->level);
}

/**
 *	@brief	ボングリ通信ジュースデータクリア
 */
static void commjuice_Clear(BONG_JUICE_COMM* comm_juice)
{
	MI_CpuClear8(comm_juice,sizeof(BONG_JUICE_COMM));
	BongJuice_Clear(&comm_juice->juice);
	PM_strclearEOM_( comm_juice->name, PERSON_NAME_SIZE+EOM_SIZE );
}


#ifdef PM_DEBUG
/**
 *	@brief	デバッグ用スタートカウントmakeカウントとまろやかカウントを取得
 *
 *	sizeof(u32)*3のバッファを渡す必要があります
 *
 *	0:作り始めの歩数
 *	1:作り始めからの差分歩数
 *	2:まろやかさカウント
 */
void BongJuiceDebug_GetWalkCount(BONGURI_SAVE* sv,u32* pc)
{

	if(!sv->stock.s_flag){
		pc[0] = 0;
		pc[1] = 0;
	}else{
		pc[0] = sv->start_ct;
		pc[1] = sv->make_ct;
	}
	pc[2] = sv->mild_ct;
}

/**
 *	@brief	デバッグ用　ストックされたぼんぐりを配列に返す
 *
 *	u8[5]のサイズを持つバッファを渡す必要があります
 */
u8 BongJuiceDebug_GetStockBonguri(BONGURI_SAVE* sv,u8* bong)
{
	int i;
	u8	num = 0;
	u16	stock = sv->stock.stock;

	for(i = 0;i < BONGJUICE_STOCK_MAX;i++){
		if(stock & BONG_STOCK_MASK_BIT){	//0でなければストックされている
			bong[i] = (stock&BONG_STOCK_MASK_BIT);
			num++;
		}else{
			bong[i] = 0;
		}
		stock >>= BONG_STOCK_SHIFT_BIT;
	}
	return num;
}

#endif	//PM_DEBUG